import axios from 'axios'
import { MessageBox } from 'element-ui';
import message from '@/utils/Message';
import store from '@/store/index'
import cookies from '@/utils/store/cookies'
import { get } from 'lodash';
import setting from '@/setting'
// 相关配置，方便移植到其他项目
const requestConfig = setting.requestConfig;
const service = axios.create({
});

// 拦截请求
service.interceptors.request.use(
    (config: any) => {
        // 获取存储在cookies中的token
        const tokenName = requestConfig.tokenName,
            token = cookies.get(tokenName);
        if (config.isToken && token && token != 'undefined') {
            // 请求头自动添加token
            config.headers[tokenName] = `${requestConfig.tokenPrefixes} ${token}`;
        }
        // 不管怎么样都要显示加载遮罩，否则遮罩类的计数逻辑会出问题
        // toastMessage为自定义配置，在发起请求时传入
        message.loading(config.toastMessage);
        return config;
    },
    error => {
        return Promise.reject(error);
    }
)
// 拦截请求结果
service.interceptors.response.use(
    (res: any) => {
        message.clear();
        // 校验登录是否过期
        const data = res.data;
        if (data && get(data, requestConfig.successProperty) == requestConfig.expiredValue) {
            MessageBox.alert("您的登录信息已过期或账号主体信息已变更，请重新登录", "提示", {
                showClose: false,
                confirmButtonClass: "btn-blue"
            }).then(() => {
                // 退出登录
                store.dispatch("account/logout");
            })
        }
        return res;
    },
    (error: any) => {
        message.clear();
        // 网络错误错误是显示提示信息
        if (error.message == "Network Error") {
            message.error(requestConfig.errorMessage);
        }
        return Promise.reject(error);
    }
)

/**
 * 获取模拟异步方法，你传入什么数据就返回什么数据
 *
 * @export
 * @param {*} data
 * @return {*} 模拟数据
 */
export function getJson(data: any): any {
    return new Promise((resolve) => {
        resolve({
            // 模拟返回成功状态
            code: requestConfig.successValue,
            success: true,
            // 传入的数据
            data: data,
            // 分页用
            total: 40
        });
    });
}

/**
 * 基础提交数据函数
 * 成功失败都有回调
 *
 * @export
 * @param {*} data axios配置
 * @param {*} options 额外配置 [{
 *         successCode = requestConfig.successValue, 提交成功状态码
 *         isSuccessToast = false,提交成功是否显示提示
 *         isNoToast = false 是否隐藏提示，为ture时不会有任何提示
 *         toastMessage = "Loading..." 遮罩提示文字
 *         isToken = true 是否带Token
 *     }={}]
 * @return {*}
 */
export function axiosRequest(data: any,
    {
        successCode = requestConfig.successValue,
        isSuccessToast = false,
        isNoToast = false,
        toastMessage = "Loading...",
        isToken = true
    }: any = {}): Promise<any> {
    return new Promise((resolve, reject) => {
        // 设置遮罩提示文字
        data.toastMessage = toastMessage;
        data.isToken = isToken;
        service.request(data).then((res: any) => {
            const data = res.data,
                // 判断提交数据结果
                success = get(data, requestConfig.successProperty) == successCode,
                // 确定消息提示类型
                type = success ? 'success' : 'error';
            // 只要isNoToast不为true,请求失败必然提升
            // isSuccessToast为ture时，请求成功也会提示
            if (isSuccessToast || !success) {
                const mes = data.msg;
                // 登录过期错误不做提示
                if (!isNoToast && data.code != requestConfig.expiredValue) {
                    message.show(mes, type);
                }
            }
            // 标识请求结果状态
            data.success = success;
            if (success) {
                resolve(res);
            } else {
                reject(data);
            }
        }).catch(() => {
            // 请求失败
            reject({
                success: false,
                data: null
            });
        });
    });
}

/**
 * 提交数据函数
 * 成功失败都有回调
 * @export
 * @param {*} data axios配置
 * @param {*} options 额外配置 [{
 *         successCode = requestConfig.successValue, 提交成功状态码
 *         isSuccessToast = false,提交成功是否显示提示
 *         isNoToast = false 提交失败是否隐藏提示
 *         toastMessage = "Loading..." 遮罩提示文字
 *         isToken = true 是否带Token
 *     }={}]
 * @returns
 */
export function ajaxBack(data: any, options?: any) {
    return new Promise((resolve, reject) => {
        axiosRequest(data, options).then((res: any) => {
            // 一般来说前端只需要res.data中的数据
            resolve(res.data);
        }).catch(res => {
            reject(res);
        });
    });
}


/**
 * get 方式提交数据
 * 无错误回调
 * @export
 * @param {string} url 地址
 * @param {*} [params] 参数
 * @param {*} options 额外配置 [{
 *         successCode = requestConfig.successValue, 提交成功状态码
 *         isSuccessToast = false,提交成功是否显示提示
 *         isNoToast = false 提交失败是否隐藏提示
 *         toastMessage = "Loading..." 遮罩提示文字
 *         isToken = true 是否带Token
 *     }={}]
 * @returns
 */
export function ajax(url: string, params?: any, options?: any) {
    return new Promise((resolve) => {
        ajaxBack({
            url: url,
            method: "get",
            params: params
        },
            options
        ).then(res => {
            resolve(res);
        }).catch(() => { });
    });
}

/**
 * 通过data提交数据，可设置数据提交方式
 * 无错误回调
 * @export
 * @param {string} method 数据提交方式
 * @param {string} url 地址
 * @param {*} [params] 参数
 * @param {*} options 额外配置 [{
 *         successCode = requestConfig.successValue, 提交成功状态码
 *         isSuccessToast = false,提交成功是否显示提示
 *         isNoToast = false 提交失败是否隐藏提示
 *         toastMessage = "Loading..." 遮罩提示文字
 *         isToken = true 是否带Token
 *     }={}]
 * @return {*}
 */
export function ajaxDataMethod(method: string, url: string, params?: any, options?: any): Promise<any> {
    return new Promise((resolve) => {
        ajaxBack({
            url: url,
            method: method,
            data: params
        },
            options
        ).then(res => {
            resolve(res);
        }).catch(() => { });
    });
}


/**
 * POST 方式提交数据
 * 无错误回调
 * @export
 * @param {string} url 地址
 * @param {*} [params] 参数
 * @param {*} options 额外配置 [{
 *         successCode = requestConfig.successValue, 提交成功状态码
 *         isSuccessToast = false,提交成功是否显示提示
 *         isNoToast = false 提交失败是否隐藏提示
 *         toastMessage = "Loading..." 遮罩提示文字
 *         isToken = true 是否带Token
 *     }={}]
 * @returns
 */
export function ajaxP(url: string, params?: any, options?: any) {
    return ajaxDataMethod("POST", url, params, options)
}
/**
 * PATCH 方式提交数据
 * 无错误回调
 * @export
 * @param {string} url 地址
 * @param {*} [params] 参数
 * @param {*} options 额外配置 [{
 *         successCode = requestConfig.successValue, 提交成功状态码
 *         isSuccessToast = false,提交成功是否显示提示
 *         isNoToast = false 提交失败是否隐藏提示
 *         toastMessage = "Loading..." 遮罩提示文字
 *         isToken = true 是否带Token
 *     }={}]
 * @returns
 */
export function ajaxH(url: string, params?: any, options?: any) {
    return ajaxDataMethod("PATCH", url, params, options)
}

/**
 * put 方式提交数据
 * 无错误回调
 * @export
 * @param {string} url 地址
 * @param {*} [params] 参数
 * @param {*} options 额外配置 [{
 *         successCode = requestConfig.successValue, 提交成功状态码
 *         isSuccessToast = false,提交成功是否显示提示
 *         isNoToast = false 提交失败是否隐藏提示
 *         toastMessage = "Loading..." 遮罩提示文字
 *         isToken = true 是否带Token
 *     }={}]
 * @returns
 */
export function ajaxPut(url: string, params?: any, options?: any) {
    return ajaxDataMethod("PUT", url, params, options)
}

/**
 * delete 方式提交数据
 * 无错误回调
 * @export
 * @param {string} url 地址
 * @param {*} [params] 参数
 * @param {*} options 额外配置 [{
 *         successCode = requestConfig.successValue, 提交成功状态码
 *         isSuccessToast = false,提交成功是否显示提示
 *         isNoToast = false 提交失败是否隐藏提示
 *         toastMessage = "Loading..." 遮罩提示文字
 *         isToken = true 是否带Token
 *     }={}]
 * @returns
 */
export function ajaxDelete(url: string, params?: any, options?: any) {
    return ajaxDataMethod("DELETE", url, params, options)
}

export default {}